// QtAudioOutputStrategy.cpp
#include "QtAudioOutputStrategy.h"
#include <iostream>
#include <QThread>
QtAudioOutputStrategy::QtAudioOutputStrategy():audioOutput(nullptr),audioDevice(nullptr) {
    print_AllAudioDevice();
    qRegisterMetaType<std::queue<float>>("std::queue<float>&");

    thread = new QThread(this);
    connect(this, &QtAudioOutputStrategy::dataReady, this, &QtAudioOutputStrategy::setData, Qt::QueuedConnection);
    moveToThread(thread);
    connect(thread, &QThread::started, this, &QtAudioOutputStrategy::threadFunction);
    thread->start();

}
void QtAudioOutputStrategy::threadFunction()
{

    QMutexLocker locker(&mutex);
    while (!initialized)
    condition.wait(&mutex);
    _init();

}
int64_t QtAudioOutputStrategy::getAudioTime(){
    // 在你需要获取音频时间的地方，使用m_audio_output->elapsedUSecs()方法
    int64_t audio_time_microsecs = audioOutput->elapsedUSecs();
//    double audio_time_secs = audio_time_microsecs / 1e6;  // 将微秒转换为秒
    return audio_time_microsecs;    
}
void QtAudioOutputStrategy::print_AllAudioDevice(){
    QList<QAudioDevice> devices = QMediaDevices::audioOutputs();
    for (const QAudioDevice & device : devices) {
        qDebug() << "Device name: " << device.description();
        // 检查设备是否支持我们的音频格式
//        if (device.isFormatSupported(format)) {
//            qDebug() << "Device supports format";
//            // 使用这个设备
//            audioOutput = new QAudioSink(device, format, this);
//            break;
//        }
    }

}
QtAudioOutputStrategy::~QtAudioOutputStrategy() {
    // print thread id
    qDebug() << "QtAudioOutputStrategy::~QtAudioOutputStrategy() thread id: " << QThread::currentThreadId();
    emit stopSignal();
    thread->wait(); // 等待线程退出
}
bool QtAudioOutputStrategy::init(){
    QMutexLocker locker(&mutex);
    initialized = true;
    condition.wakeOne();
    return true;
}

bool QtAudioOutputStrategy::_init(){

    QAudioFormat format;
    // 创建一个QAudioFormat对象，并设置音频数据的格式
    format.setSampleRate(44100);
    format.setChannelCount(2);
    format.setSampleFormat(QAudioFormat::Float);

    // 获取默认的音频输出设备
    defaultDevice = QMediaDevices::defaultAudioOutput();

    // 检查设备是否支持我们的音频格式
    if (!defaultDevice.isFormatSupported(format)) {
        qWarning() << "Default device does not support format, trying to use the preferred format.";
        format = defaultDevice.preferredFormat();
        qDebug() << "\t defaultDevice Sample rate: " << defaultDevice.preferredFormat().sampleRate();
        qDebug() << "\t defaultDevice Channel count: " << defaultDevice.preferredFormat().channelCount();
        qDebug() << "\t defaultDevice Sample format: " << defaultDevice.preferredFormat().sampleFormat();

         //You can also choose another audio device !
    }


 //   qDebug() << "end format:";
    qDebug() << "Device name: " << defaultDevice.description();
    qDebug() << "\tSample rate: " << format.sampleRate();
    qDebug() << "\tChannel count: " << format.channelCount();
    qDebug() << "\tSample format: " << format.sampleFormat();

    audioOutput = new QAudioSink(defaultDevice,format,this);
    int bytesPerSample;
    switch(format.sampleFormat()) {
    case QAudioFormat::Float:
        bytesPerSample = sizeof(float);
        break;
    case QAudioFormat::Int16:
        bytesPerSample = sizeof(short);
        break;
    default:
        qWarning() << "Unsupported sample format";
        return 0;
    }

    qint64 bufferSize = format.sampleRate() * format.channelCount() * bytesPerSample * 1;
    bufferSize -= bufferSize % (format.channelCount() * bytesPerSample);
    qDebug()<<"audio bufferSize:" << bufferSize;

    audioOutput->setBufferSize(bufferSize);

    connect(audioOutput, SIGNAL(stateChanged(QAudio::State)), this, SLOT(handleStateChanged(QAudio::State)));
    connect(this, &QtAudioOutputStrategy::stopSignal, this, &QtAudioOutputStrategy::stopSlot);

    return true;
}
void QtAudioOutputStrategy::stopSlot()
{
    // print thread id
    qDebug() << "QtAudioOutputStrategy::stopSlot() thread id: " << QThread::currentThreadId();
    if (audioOutput) {
        audioOutput->stop();
    }
    if (thread) {
        thread->quit();
    }
}
void QtAudioOutputStrategy::handleStateChanged(QAudio::State newState)
{
    switch (newState) {
        case QAudio::IdleState:
          qDebug()<<"   Finished playing (no more data)";
            // Finished playing (no more data)
         //   audioOutput->stop();

       //     delete audioOutput;
            break;

        case QAudio::StoppedState:
          qDebug()<<"  StoppedState:"<<audioOutput->error() ;
            // Stopped for other reasons
            if (audioOutput->error() != QAudio::NoError) {
                // Error handling
            }
            break;

        default:
                qDebug()<<"  newState:"<<newState;
            break;
    }
}
bool QtAudioOutputStrategy::stop() {
    if (audioOutput) {
        // 停止音频播放
        audioOutput->stop();

        return true;
    } else {
        return false;
    }
}
void QtAudioOutputStrategy::checkError() {
    if (audioOutput) {
        QAudio::Error error = audioOutput->error();
        switch (error) {
            case QAudio::NoError:
                qDebug() << "No error";
                break;
            case QAudio::OpenError:
                qDebug() << "Open error";
                break;
            case QAudio::IOError:
                qDebug() << "IO error";
                break;
            case QAudio::UnderrunError:
                qDebug() << "Underrun error";
                break;
            case QAudio::FatalError:
                qDebug() << "Fatal error";
                break;
            default:
                qDebug() << "Unknown error";
                break;
        }
    }
}
void QtAudioOutputStrategy::setData(std::queue<float>& data) {
    // 1. 提取并转换数据，尽量减少锁持有时间
    QByteArray byteArray;
    {
        QMutexLocker locker(&mutex);
        byteArray.reserve(data.size() * sizeof(float)); // 预分配内存
        while (!data.empty()) {
                float value = data.front();
                data.pop();
                byteArray.append(reinterpret_cast<const char*>(&value), sizeof(float));
        }
    }

    // 2. 检查音频设备状态
    if (!audioOutput) return;

    if (!audioDevice) {
        audioDevice = audioOutput->start();
        if (!audioDevice) {
                std::cerr << "Failed to start audio output." << std::endl;
                return;
        } else {
                qDebug() << "Start audio output successfully";
        }
    }

    if (!audioDevice->isOpen() || !audioDevice->isWritable()) {
        qDebug() << "Audio device not open or not writable";
        return;
    }

    // 3. 非阻塞写入操作（可选：在独立线程中执行）
//    if (!byteArray.isEmpty()) {
        qint64 bytesWritten = audioDevice->write(byteArray);
        if (bytesWritten == -1) {
                std::cerr << "An error occurred: " << audioDevice->errorString().toStdString() << std::endl;
                // 尝试重新启动音频设备
                audioOutput->stop(); // 使用 QAudioOutput 的 stop 方法
                audioDevice = audioOutput->start();
        } else {
            //qDebug() << "Bytes written:" << bytesWritten;
            // 记录总写入字节数
            //qDebug() << "Total bytes written:" << bytesWritten;
        }
//    }
}



bool QtAudioOutputStrategy::play()    {
    if (audioOutput) {
        // 检查音频输出的状态
        if (audioOutput->state() != QAudio::ActiveState) {
            qWarning() << "Audio output is not active.";
            return false;
        }

        return true;
    } else {
        return false;
    }
    return true;
}
